/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import java.security.InvalidParameterException;
import java.util.Arrays;

/**
 * Calculates the multiplied result of two matrices using simple serial calculation.
 *
 * @author Corvus
 */
public class SerialMatrixCalculator {

    private double[][] source_matrix_A;
    private double[][] source_matrix_B;

    /**
     * Initializes the calculator ready to do the calculation.
     * 
     * @param a The first matrix
     * @param b The second matrix
     */
    public SerialMatrixCalculator(double[][] a, double[][] b) {
        if (a == null) {
            throw new InvalidParameterException("First matrix is null.");
        }
        if (b == null) {
            throw new InvalidParameterException("Second matrix is null.");
        }

        if (a[0].length != b.length) {
            throw new InvalidParameterException("Invalid matrix sizes");
        }

        this.source_matrix_A = a;
        this.source_matrix_B = b;
    }

    /**
     * Does the calculation.
     * O(n^3)
     * 
     * @return The result matrix.
     */
    public double[][] calculate() {
        int targetMatrixXSize = source_matrix_B[0].length;
        int targetMatrixYSize = source_matrix_A.length;

        double[][] target_matrix = new double[targetMatrixYSize][targetMatrixXSize];

        for (int y = 0; y < targetMatrixYSize; y++) {
            for (int x = 0; x < targetMatrixXSize; x++) {
                target_matrix[y][x] = calculateNode(y, x);
            }

            if (y % 100 == 0) {
                Main.print(y + "/" + targetMatrixYSize + " rows done");
            }
        }

        return target_matrix;
    }

    /**
     * Calculates the result matrix's node's value.
     * 
     * @param y Node's y coordinate
     * @param x Node's x coordinate
     * @return The node's value
     */
    private int calculateNode(int y, int x) {
        int value = 0;
        for (int i = 0; i < source_matrix_A[y].length; i++) {
            value += source_matrix_A[y][i] * source_matrix_B[i][x];
        }
        return value;
    }

    public static void main(String[] args) {
        double[][] a = {{14, 9, 3}, {2, 11, 15}, {0, 12, 17}, {5, 2, 3}};
        double[][] b = {{12, 25}, {9, 10}, {8, 5}};


        for (int i = 0; i < a.length; i++) {
            System.out.println(Arrays.toString(a[i]));
        }
        for (int i = 0; i < b.length; i++) {
            System.out.println(Arrays.toString(b[i]));
        }

        SerialMatrixCalculator smc = new SerialMatrixCalculator(a, b);
        double[][] result = smc.calculate();

        for (int i = 0; i < result.length; i++) {
            System.out.println(Arrays.toString(result[i]));
        }
    }
}
